<!-- 折线图，支持多组数据，支持阶梯式动画效果 -->
<template>
  <div ref="chartRef" class="art-line-chart" :style="{ height: props.height }" v-loading="props.loading">
    <ArtChartEmpty v-if="isEmpty" />
  </div>
</template>

<script setup lang="ts">
import * as echarts from 'echarts'
import type { EChartsOption } from 'echarts'
import { getCssVar, hexToRgba } from '@/utils/ui'
import { useChartOps, useChart } from '@/composables/useChart'
import type { LineChartProps, LineDataItem } from '@/types/component/chart'

defineOptions({ name: 'ArtLineChart' })

const props = withDefaults(defineProps<LineChartProps>(), {
  // 基础配置
  height: useChartOps().chartHeight,
  loading: false,
  isEmpty: false,
  colors: () => useChartOps().colors,

  // 数据配置
  data: () => [0, 0, 0, 0, 0, 0, 0],
  xAxisData: () => [],
  lineWidth: 2.5,
  showAreaColor: false,
  smooth: true,
  symbol: 'none',
  symbolSize: 6,
  animationDelay: 200,

  // 轴线显示配置
  showAxisLabel: true,
  showAxisLine: true,
  showSplitLine: true,

  // 交互配置
  showTooltip: true,
  showLegend: false,
  legendPosition: 'bottom'
})

// 使用基础的 useChart hook
const {
  chartRef,
  isDark,
  initChart,
  getAxisLineStyle,
  getAxisLabelStyle,
  getAxisTickStyle,
  getSplitLineStyle,
  getTooltipStyle,
  getLegendStyle,
  getGridWithLegend
} = useChart()

// 动画状态和定时器管理
const isAnimating = ref(false)
const animationTimer = ref<ReturnType<typeof setTimeout>>()
const animatedData = ref<number[] | LineDataItem[]>([])

// 清理定时器
const clearAnimationTimer = () => {
  if (animationTimer.value) {
    clearTimeout(animationTimer.value)
    animationTimer.value = undefined
  }
}

// 检查是否为空数据
const isEmpty = computed(() => {
  if (props.isEmpty) return true

  // 检查单数据情况
  if (Array.isArray(props.data) && typeof props.data[0] === 'number') {
    const singleData = props.data as number[]
    return !singleData.length || singleData.every((val) => val === 0)
  }

  // 检查多数据情况
  if (Array.isArray(props.data) && typeof props.data[0] === 'object') {
    const multiData = props.data as LineDataItem[]
    return (
      !multiData.length ||
      multiData.every((item) => !item.data?.length || item.data.every((val) => val === 0))
    )
  }

  return true
})

// 判断是否为多数据
const isMultipleData = computed(() => {
  return (
    Array.isArray(props.data) &&
    props.data.length > 0 &&
    typeof props.data[0] === 'object' &&
    'name' in props.data[0]
  )
})

// 缓存计算的最大值，避免重复计算
const maxValue = computed(() => {
  if (isMultipleData.value) {
    const multiData = props.data as LineDataItem[]
    return multiData.reduce((max, item) => {
      if (item.data?.length) {
        const itemMax = Math.max(...item.data)
        return Math.max(max, itemMax)
      }
      return max
    }, 0)
  } else {
    const singleData = props.data as number[]
    return singleData?.length ? Math.max(...singleData) : 0
  }
})

// 初始化动画数据
const initAnimationData = () => {
  if (isMultipleData.value) {
    const multiData = props.data as LineDataItem[]
    return multiData.map((item) => ({
      ...item,
      data: new Array(item.data.length).fill(0)
    }))
  } else {
    const singleData = props.data as number[]
    return new Array(singleData.length).fill(0)
  }
}

// 复制真实数据
const copyRealData = () => {
  return isMultipleData.value
    ? [...(props.data as LineDataItem[])]
    : [...(props.data as number[])]
}

// 获取颜色配置
const getColor = (customColor?: string, index?: number) => {
  if (customColor) return customColor

  if (index !== undefined) {
    return props.colors![index % props.colors!.length]
  }

  return getCssVar('--el-color-primary')
}

// 生成区域样式
const generateAreaStyle = (item: LineDataItem, color: string) => {
  // 如果有 areaStyle 配置，或者显式开启了区域颜色，则显示区域样式
  if (!item.areaStyle && !item.showAreaColor && !props.showAreaColor) return undefined

  const areaConfig = item.areaStyle || {}
  if (areaConfig.custom) return areaConfig.custom

  return {
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: hexToRgba(color, areaConfig.startOpacity || 0.2).rgba
      },
      {
        offset: 1,
        color: hexToRgba(color, areaConfig.endOpacity || 0.02).rgba
      }
    ])
  }
}

// 生成单数据区域样式
const generateSingleAreaStyle = () => {
  if (!props.showAreaColor) return undefined

  const color = getColor(props.colors[0])
  return {
    color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
      {
        offset: 0,
        color: hexToRgba(color, 0.2).rgba
      },
      {
        offset: 1,
        color: hexToRgba(color, 0.02).rgba
      }
    ])
  }
}

// 创建系列配置
const createSeriesItem = (config: {
  name?: string
  data: number[]
  color?: string
  smooth?: boolean
  symbol?: string
  symbolSize?: number
  lineWidth?: number
  areaStyle?: any
}) => {
  return {
    name: config.name,
    data: config.data,
    type: 'line' as const,
    color: config.color,
    smooth: config.smooth ?? props.smooth,
    symbol: config.symbol ?? props.symbol,
    symbolSize: config.symbolSize ?? props.symbolSize,
    lineStyle: {
      width: config.lineWidth ?? props.lineWidth,
      color: config.color
    },
    areaStyle: config.areaStyle,
    emphasis: {
      focus: 'series' as const,
      lineStyle: {
        width: (config.lineWidth ?? props.lineWidth) + 1
      }
    }
  }
}

// 生成图表配置
const generateChartOptions = (isInitial = false): EChartsOption => {
  const options: EChartsOption = {
    animation: true,
    animationDuration: isInitial ? 0 : 1300,
    animationDurationUpdate: isInitial ? 0 : 1300,
    grid: getGridWithLegend(props.showLegend && isMultipleData.value, props.legendPosition, {
      top: 15,
      right: 15,
      left: 0
    }),
    tooltip: props.showTooltip ? getTooltipStyle() : undefined,
    xAxis: {
      type: 'category',
      boundaryGap: false,
      data: props.xAxisData,
      axisTick: getAxisTickStyle(),
      axisLine: getAxisLineStyle(props.showAxisLine),
      axisLabel: getAxisLabelStyle(props.showAxisLabel)
    },
    yAxis: {
      type: 'value',
      min: 0,
      max: maxValue.value,
      axisLabel: getAxisLabelStyle(props.showAxisLabel),
      axisLine: getAxisLineStyle(props.showAxisLine),
      splitLine: getSplitLineStyle(props.showSplitLine)
    }
  }

  // 添加图例配置
  if (props.showLegend && isMultipleData.value) {
    options.legend = getLegendStyle(props.legendPosition)
  }

  // 生成系列数据
  if (isMultipleData.value) {
    const multiData = animatedData.value as LineDataItem[]
    options.series = multiData.map((item, index) => {
      const itemColor = getColor(props.colors[index], index)
      const areaStyle = generateAreaStyle(item, itemColor)

      return createSeriesItem({
        name: item.name,
        data: item.data,
        color: item.lineColor ? item.lineColor : itemColor,
        smooth: item.smooth,
        symbol: item.symbol,
        lineWidth: item.lineWidth,
        areaStyle
      })
    })
  } else {
    // 单数据情况
    const singleData = animatedData.value as number[]
    const computedColor = getColor(props.colors[0])
    const areaStyle = generateSingleAreaStyle()

    options.series = [
      createSeriesItem({
        data: singleData,
        color: computedColor,
        areaStyle
      })
    ]
  }

  return options
}

// 更新图表
const updateChart = (options: EChartsOption) => {
  if (!isEmpty.value) {
    initChart(options)
  }
}

// 初始化动画函数（优化多数据阶梯式动画效果）
const initChartWithAnimation = () => {
  if (!isEmpty.value) {
    clearAnimationTimer()
    isAnimating.value = true

    // 如果是多数据情况，使用阶梯式动画
    if (isMultipleData.value) {
      const multiData = props.data as LineDataItem[]

      // 先将数据初始化为0
      animatedData.value = initAnimationData()
      updateChart(generateChartOptions(true))

      // 阶梯式更新每组数据
      multiData.forEach((item, index) => {
        setTimeout(
          () => {
            // 逐个更新数据组
            const currentAnimatedData = animatedData.value as LineDataItem[]
            currentAnimatedData[index] = { ...item }
            animatedData.value = [...currentAnimatedData]
            updateChart(generateChartOptions(false))
          },
          index * props.animationDelay + 100
        )
      })

      // 标记动画完成
      const totalDelay = (multiData.length - 1) * props.animationDelay + 1500
      setTimeout(() => {
        isAnimating.value = false
      }, totalDelay)
    } else {
      // 单数据情况保持原有的简单动画
      animatedData.value = initAnimationData()
      updateChart(generateChartOptions(true))

      animationTimer.value = setTimeout(() => {
        animatedData.value = copyRealData()
        updateChart(generateChartOptions(false))
        isAnimating.value = false
      }, 100)
    }
  } else {
    animatedData.value = copyRealData()
    updateChart(generateChartOptions(false))
  }
}

// 图表渲染函数
const renderChart = () => {
  initChartWithAnimation()
}

// 处理图表进入可视区域时的动画
const handleChartVisible = () => {
  // 当图表变为可见时，也使用相同的动画逻辑
  initChartWithAnimation()
}

// 监听数据变化 - 优化监听器，减少不必要的重新渲染
watch(
  [() => props.data, () => props.xAxisData, () => props.colors],
  () => {
    // 只有在不播放动画时才触发重新渲染
    if (!isAnimating.value) {
      renderChart()
    }
  },
  { deep: true }
)

// 监听主题变化 - 使用setOption更新而不是重新渲染
watch(isDark, () => {
  // 获取图表实例
  const chartInstance =
    (chartRef.value as any)?.__echart__ || echarts.getInstanceByDom(chartRef.value as HTMLElement)

  if (chartInstance && !isEmpty.value) {
    // 重新生成配置并更新图表，避免重新渲染
    const newOptions = generateChartOptions(false)
    chartInstance.setOption(newOptions)
  }
})

// 生命周期
onMounted(() => {
  renderChart()

  // 监听图表可见事件
  if (chartRef.value) {
    chartRef.value.addEventListener('chartVisible', handleChartVisible)
  }
})

onBeforeUnmount(() => {
  clearAnimationTimer()

  // 清理事件监听器
  if (chartRef.value) {
    chartRef.value.removeEventListener('chartVisible', handleChartVisible)
  }
})
</script>

<style lang="scss" scoped>
.art-line-chart {
  position: relative;
  width: calc(100% + 10px);
}
</style>
